import classNames from 'classnames';
import React, { forwardRef, useCallback, useRef } from 'react';
import useStatus, { isActive } from './hooks/useStatus';
import type { MotionChildrenFirstProps, YmCssMotionProps } from './interface';
import { STATUS_NONE, STEP_PREPARE, STEP_START } from './interface';

const CssMotion = forwardRef<any, YmCssMotionProps>((props, ref) => {
  const {
    visible = false,
    motionName,
    forceRender = false,
    removeOnLeave = true,
    leavedClassName,
    children,
    childrenFnParams,
    ...restProps
  } = props;

  const nodeRef = useRef<HTMLElement>();

  function getTargetElement(): HTMLElement | undefined {
    return nodeRef.current;
  }

  const setTargetElement = useCallback<(node: HTMLElement) => void>(
    (node) => {
      nodeRef.current = node;
      if (ref) {
        (ref as { current: HTMLElement }).current = node;
      }
    },
    [ref],
  );

  const [status, statusStep, statusStyle] = useStatus(
    visible,
    getTargetElement,
    restProps,
  );

  let motionChildren: React.ReactNode;

  //motionChildren场景
  //1.初始化visible:true/进来之后的样子 -- 干干净净,原本的样式
  //2.初始化visible:false/出去之后的样子 -- display:none/ leavedClassName  / null
  //3.执行进场/出场动画

  if (!children) {
    return null;
  }

  if (status === STATUS_NONE) {
    // 'none'
    if (visible) {
      //场景1
      motionChildren = children(
        { visible, ...childrenFnParams },
        setTargetElement,
      );
    } else {
      //场景2
      let childFnProps: MotionChildrenFirstProps = {};
      if (forceRender) {
        childFnProps = leavedClassName
          ? { className: leavedClassName }
          : { style: { display: 'none' } };
        motionChildren = children(
          { visible, ...childFnProps, ...childrenFnParams },
          setTargetElement,
        );
      } else {
        if (removeOnLeave) {
          motionChildren = null;
        } else {
          childFnProps = leavedClassName
            ? { className: leavedClassName }
            : { style: { display: 'none' } };
          motionChildren = children(
            { visible, ...childFnProps, ...childrenFnParams },
            setTargetElement,
          );
        }
      }
    }
  } else {
    //场景3
    let statusSuffix;
    if (statusStep === STEP_PREPARE) {
      //prepare
      statusSuffix = 'prepare';
    } else if (statusStep === STEP_START) {
      //start
      statusSuffix = 'start';
    } else if (isActive(statusStep)) {
      //active , end
      statusSuffix = 'active';
    }
    motionChildren = children(
      {
        visible,
        className: classNames(
          motionName,
          `${motionName}-${status}`,
          `${motionName}-${status}-${statusSuffix}`,
        ),
        style: statusStyle,
        ...childrenFnParams,
      },
      setTargetElement,
    );
  }

  return motionChildren;
});

export default CssMotion;
